Syntaxe : (valeur_1, valeur_2, ...)
Les Aggregates sont des groupements de valeurs formant des tableaux ou des enregistrements. La première forme ci-dessous est appelée association positionnelle, où les valeurs sont associées aux éléments de la gauche vers la droite.
signal Z_BUS : bit_vector (3 downto 0);
signal A_BIT, B_BIT, C_BIT, D_BIT : bit;
Association équivalente : Z_BUS(3) <= A_BIT;
Z_BUS(1) <= C_BIT;
signal A_BIT, B_BIT, C_BIT, D_BIT : bit;
Z_BUS <= (2 => B_BIT, 1 => C_BIT, 0 => D_BIT, 3 => A_BIT);
signal BYTE : bit_vector (7 downto 0);
BYTE <= (7 => '1', 5 downto 1 => '1', 6 => B_BIT, others => '0');
BYTE_ID : std_ulogic;
PARITY : std_ulogic;
ADDRESS : integer range 0 to 3;
DATA : std_ulogic_vector(3 downto 0);
end record;
signal TX_DATA : T_PACKET;
TX_DATA <= ('1', '0', 2, "0101");
type MEM is array (0 to 7) of NIBBLE;
variable MEM8X4: MEM := (others => "0000");
variable D_BUS : std_ulogic_vector(63 downto 0) := (others => 'Z');
Les outils de synthèse ne supportent pas complètement l’association par nom. Ainsi, l’assignation d’enregistrement utilisant les aggregates n’est pas supportée.
Syntaxe : alias nom_alias : type_alias is nom_objet;
Règles et Exemples
Un alias est un autre nom pour un objet existant (signal, variable ou constant). Il ne doit pas définir un nouvel objet :
alias OPERAND : bit_vector(1 downto 0) is CPU_BUFFER(LOW) (4 downto 3);
alias A : bit_vector(3 downto 0) is CPU_BUFFER(HIGH)(3 downto 0);
alias B : bit_vector(2 downto 0) is CPU_BUFFER(LOW) (2 downto 0);
...
L’alias d’un tableau peut être indexé en sens contraire :
alias BIT_REV_A : std_ulogic_vector(0 to 7) is BUS_A;
Les alias ne sont pas supportés par la plupart des outils de synthèse.
Syntaxe : architecture arch_name of entity_name is
begin
concurrent statements
end arch_name;
Les déclarations peuvent être : type, subtype, signal, constant, file, alias, component, attribut, function, procedure ou configuration :
component CPU_IF
port -- liste des entrées et sorties ...
end component;
signal CPU_DATA_VALID : std_ulogic;
signal CLK, RESET : std_ulogic := '0';
constant PERIOD : time := 10 ns;
constant MAX_SIM : time := 50 * PERIOD;
begin
-- instructions simultanées
end TB;
signal Z,A,B,C,D :integer;
begin
D <= A + B;
Z <= C + D;
end EX1;
Une architecture équivalente :
signal Z,A,B,C,D :integer;
begin
Z <= C + D;
D <= A + B;
end EX2;
component DFF
port (CLK, D : in std_ulogic;
Q : out std_ulogic);
end component;
signal CLK, D, Q : std_ulogic := '0';
begin
UUT: DFF port map (CLK, D, Q);
CLK <= not (CLK) after 25 ns;
STIMULUS: process
begin
wait for 50 ns;
D <= '1';
wait for 100 ns;
D <= '0';
wait for 50 ns;
end process STIMULUS;
end TEST;
Une Architecture ne peut pas être analysée à moins que l’entité à laquelle elle se réfère n’existe dans la librairie de projet (design library).
Effets sur la synthèse
Les architectures sont totalement supportées par les outils de synthèse dans la mesure ou les déclarations et les instructions quelles comportent soient compatibles avec la synthèse.
Syntaxe : type nom_type is array (range) of type_element;
Règles et Exemples
Un array contient plusieurs éléments d’un même type. Lorsqu’un tableau est déclaré, il doit correspondre à un type tableau existant.
type RAM is array (0 to 31) of integer range 0 to 255;
signal A_BUS : NIBBLE;
signal RAM_0 : RAM;
variable INT_TABLE: INT_ARRAY(0 to 9);
variable LOC_BUS : std_ulogic_vector(7 downto 0);
A_BUS <= "0000";
LOC_BUS := "10101010";
-- une assignation équivalante:
A_BUS <= A_BIT & B_BIT & C_BIT & D_BIT;
-- rotation de A_BUS vers la gauche:
A_BUS <= A_BUS(2 downto 0) & A_BUS(3);
type MEM is array (0 to 7) of NIBBLE;
-- le type tableau de tableau
variable MEM8X4: MEM;
-- accession à tout le tableau:
MEM8X4 := ("0000","0001","0010","0011","0100","0101","0110","0111");
-- accéder à un "mot":
MEM8X4(5) := "0110";
-- accéder à un seul "bit":
MEM8X4(6) (0) := '0';
signal X_2D : T_2D;
X_2D <= ((0,0), (1,1), (2,2), (3,3));
X_2D(3,1) <= 4;
La plupart des outils de synthèse acceptent les tableaux à une dimension.
Comme une instruction simultanée, une Assertion peut être utilisée dans une entity ou une architecture. Comme une instruction séquentielle, une Assertion peut être utilisée dans un process, une function ou une procedure.
Syntaxe : assert condition report chaîne_de_caractères severity niveau_de_sévérité;
Règles et Exemples
L’instruction Assert teste une condition booléenne. Si elle est fausse, elle affiche le message contenu dans la chaîne de caractère sur l’écran du simulateur :
assert not(OVERFLOW) report "Dépassement de capacité de l’accumulateur" severity failure;
Si la clause message est omise, un message par défaut est affiché. Le niveau de sévérité ainsi que le nom de l’élément de projet (design unit) contenant l’instruction assert sont affichés.
Si la clause de sévérité est omise, le niveau par défaut est error.
Une instruction simultanée assert teste continuellement la condition booléenne.
En utilisant le mot false comme condition on provoque l’affichage inconditionnel du message :
signal ITEM : in T_DATA) is
begin
if (POINTER < 5) then
STACK(POINTER) <= ITEM;
POINTER <= POINTER + 1;
else assert false report "Dépassement de capacité de la pile" severity error;
end if;
end PUT;
begin
if (CLK'event and CLK='1') then assert D'stable(SETUP_TIME)
report " Violation de Setup..." severity warning;
end if;
end process CHECK_SETUP;
L’instruction assert n’est pas prise en compte par les outils de simulation.
Syntaxe : objet'nom_attribute
Règles et Exemples
Les attributes fournissent des informations supplémentaires sur : signal, variable, type ou componant. Certains attributes sont prédéfinis pour : type, array et signal.
Voici quelques attributes prédéfinis pour le type scalar, array avec contrainte.
X'high La borne supérieure de X
X'low La borne inférieure de X
X'left La limite à gauche de X
X'right La limite à droite de X
X'range L’intervalle de X
X'reverse_range L’intervalle de X à rebours
X'length X'high - X'low + 1 (entier)
X'event Vrai lorsque X change (booléen)
X'active Vrai lorsque X est affecté (booléen)
X'last_event Lorsque X a fini d’évoluer (durée)
X'last_active Lorsque X a fini d’être affecté (durée)
X'last_value Précédente valeur de X (même type que X)
X'delayed(T) X, retardé de T (même type que X)
X'stable(T) Vrai si X reste inchangé pendant une durée T (booléen)
X'quiet(T) Vrai si X n’est pas affecté pendant un durée T (booléen)
X'transaction "Toggles" lorsque X est affecté (bit)
attribute PTYPE : IC_PACKAGE;
attribute PTYPE of U1: component is PLCC;
attribute PTYPE of U2: component is DIL;
Les outils de synthèse usuels supportent les attributes ‘high, 'low, 'left, 'right, 'range, 'reverse_range, 'length et 'event. Certains outils supportent 'last_value et 'stable.
Syntaxe : label: block (condition_de_garde_optionnelle)
begin
Le label est obligatoire :
begin
U1: CONTROLLER_A port map (CLK,X,Y,Z);
U2: CONTROLLER_A port map (CLK,A,B,C);
begin
U3: DATAPATH_A port map (BUS_A,BUS_B,BUS_C,Z);
U4: DATAPATH_B port map (BUS_A,BUS_C,BUS_D,C);
end block DATA_PATH;
Effets sur la synthèse
Les blocks sans condition de garde sont " mis à plat " par les outils de synthèse.
Syntaxe : case expression is
end case;
Tous les choix possibles doivent être inclus, à moins que la clause others ne soit utilisée comme dernier choix :
when "01" => Z <= A;
when "10" => Z <= B;
when others => Z <= 'X';
end case;
when 0 => Z <= A;
when 1 to 3 => Z <= B;
when 4|6|8 => Z <= C;
when others => Z <= 'X';
end case;
when 0 => Z <= A;
when 1 to 3 => Z <= B;
when 2|6|8 => Z <= C; ***
when others => Z <= 'X';
end case;
when "000" to "010" => Z <= A; ***
when "111" => Z <= B;
when others => Z <='X';
end case;
L’instruction case est en général synthètisable.
Syntaxe : component nom_du_composant
port (list_des_E/S);
La liste d’entrées et sortie doit définir le nom, le mode (direction) et le type de chaque entrée et sortie du composant :
component DEMIADD
La déclaration de component ne définit pas la paire entity-architecture qui sera associé à chaque instance, ou les entrées et sorties de l’entity. Ceci est fait par la configuration.
Dans une architecture, les components doivent être déclarés avant l’instruction begin :
-- (Ici déclarations locale des signaux)
component PORTEOU
port (A,B : in bit; Z : out bit);
end component;
-- (Déclarations des autres components)
begin
-- Contenu de l’architecture
end STRUCTURE;
Les generics doivent être déclarés avant les ports.
generic (N : integer);
port (A : in std_ulogic_vector (N-1 downto 0);
ODD : out std_ulogic);
end component;
Les outils de synthèse supporte les components.
Syntaxe : label-de_l’insatnce: nom_du_composant
port map (liste_des_E/S_associées);
Le label de l’instance est obligatoire. Le nom du composant doit correspondre au nom de la déclaration :
signal X,Y,S,C : bit;
component DEMIADD
port(A,B : in bit;
SUM, CARRY : out bit);
end component;
begin
U1: DEMIADD port map (X,Y,S,C);
-- autres instructions
end STRUCT;
Une autre possibilité est l’association par nom, où les entrées et sorties sont explicitement référencées :
generic map ( N => 8)
port map ( A => DATA_BYTE, ODD => PARITY_BYTE);
L’instanciation de composants est supportée par les outils de synthèse, generic map est ignoré.
syntaxe : configuration nom_de_config of nom_d’entité is
for label_ d’instance: nom_de_composant
use entity
nom_lib.nom_entité(nom_arch);
for nom_arch
-- bas niveau de spécifications de configurations
...
end for;
end for;
end for;
end nom_de_config;
configuration nom_de_config of nom_d’entité is
for nom_d’architecture
for label_ d’instance: nom_de_composant
use configuration nom_lib.nom_cfg;
end for;
end for;
Avec la première forme de configuration de component ci-dessus, la totalité de la hiérarchie peut être configurée à partir d’une seule déclaration. La seconde forme ci-dessus est constituée d’un " arbre " de déclarations de configuration. En l’absence d’une configuration explicite les liens par défaut sont appliqués. Pour chaque instance de composant, une entité sera sélectionnée ; son nom, le nom de ses ports et le type des port correspondant à ceux de la déclaration de component.
Le mot clé all peut être utilisé pour se référer à toutes les instances d’un composant.
for STRUCTURE
for all : DEMIADD use entity work.DEMIADD(COMPORT);
end for;
end for;
end CFG_ADD;
for STRUCTURE
for all : DEMIADD use entity work.HA(B)
port map(X => A, Y => B, S => SUM, C => CARRY);
end for;
end for;
end CFG_ADD;
La configuration n’est en général pas supportée par les outils de synthèse.
Syntaxe : for label_d’instance: nom_du_composant use entity nom_lib.nom_entity(nom_arch);
Pour utiliser une spécification de configuration, les components doivent être configurés à l’intérieur de l’architecture qui les instancie.
Architecture STR of XA is
componant DEMIADD port (A,B in bit ; SUM, CARRY :out bit) ;
end component ;
componant ORGATE port (A,B : in bit ; Z :out bit) ;
end component ;
for U1 : DEMIADD use entity work.HA(BEHAVE) ;
for U1 : ORGATE use entity work.OG(BEHAVE) ;
begin
U1 : DEMIADD port map (A, B, S, C) ;
U2 : ORGATE port map (A,B,Y) ;
end STR ;
Le mot clé all peut être utilisé pour faire référence à toutes les instances d’un component.
For all : ADDI use entity work.ADDI(STRUCTURAL) ;
Le mot clé others peut être utilisé pour faire référence à toutes les instances non explicitement mentionnées.
Si les noms des ports d’une entity ne correspondent pas à la déclaration du component. Une assocoation de port map doit êtte incluse dans la configuration.
For all : DEMIADD use entity work.DEMIADD(BEHAV)
port map (X => A, Y => B, S => SUM, C => CARRY) ;
Effets sur la synthèse
Les configurations ne sont en général pas supportées par les outils de synthèse.
Syntaxe : constant constant_name : type := value;
Règles et Exemples
constant BUS_WIDTH : integer := 8;
constant FOUR_ONES :std_logic_vector(3 downto 0):= "1111";
constant PERIOD : time := 10 ns;
constant MAX_SIM_TIME :time := 50 * PERIOD;
Les valeurs d’un tableau de constantes de types autres que string, bit_vector et std_logic_vector, doit être fixé en utilisant des aggregates.
type T_CLOCK_TIME is ARRAY(3 downto 0) of integer range 0 to 9;
constant TWELVE_O_CLOCK : T_CLOCK_TIME := (1,2,0,0);
Dans un package une constante doit être différée. Cela signifie que sa valeur est définie dans le package body. Sa valeur peut être modifiée en re-analysant seulement le package body:
package P is
constant C : integer;
end P;
package body P is
constant C : integer := 200;
end P;
Pourvues d’un type correct, les constantes peuvent être utilisées dans n’importe quelle expression. Elles peuvent être associées aux generics d’instance de component et passées dans les procedures:
type T_DATA is array (0 to 3) of bit_vector(7 downto 0);
constant DATA : T_DATA := ("00001000", "00010001", "00100010", "01000011");
begin
for I in DATA'range loop serialize_byte(DATA(I),DOUT);
end loop;
end process;
Les constantes sont supportées pour la synthèse.
Syntaxe : entity entity_name is generic (generic_list);
end entity_name;
La liste de port doit définir le nom, le mode (la direction) et le type de chaque port de l’entity:
port(A,B : in bit; SUM, CARRY : out bit);
end DEMIADD;
entity COUNTER is
port (CLK : in std_ulogic; RESET: in std_ulogic; Q : out integer range 0 to 15);
end COUNTER;
end TB_DISPLAY;
architecture TEST of TB_DISPLAY is
-- signal declarations
-- component declaration(s)
begin
-- component instance(s)
-- test processes
end TEST;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Si une entity a des generics, ils doivent être déclarés avant les ports. Ils ne doivent pas avoir de mode, par définition ils ne peuvent que passer des informations dans l’entity:
generic (DELAY: time := 1.0 ns);
port (A,B : in std_ulogic; Z : out std_ulogic);
end AN2_GENERIC;
Effets sur la synthèse
Les Entity declarations sont supportées pour la synthèse.
Syntaxe : exit;
exit loop_label when condition;
L’instruction exit est utilisée pour terminer une boucle infinie :
end if;
end loop;
variable I : integer range 0 to 4;
begin
Z <= "0000";
I := 0;
loop exit when I = 4;
if (A = I) then Z(I) <= '1';
end if;
I := I + 1;
end loop;
end process;
L2: for J in 0 to 7 loop
exit L1 when QUIT_BOTH_LOOPS = '1';
exit when QUIT_INNER_LOOP = '1';
-- other statements
end loop L2;
end loop L1;
L’instruction exit est supportée par certains outils de synthèse.
Syntaxe : file logical_name : file_type is mode "file_name";
Règles et Exemples
Habituellement on utilise des fichiers de type texte, car ils sont portables sur différents simulateurs VHDL. Le mode du fichier fait référence à la direction du flot de données, il peut être in (c.a.d. fichier à lecture seule) ou out (c.a.d fichier en écriture):
package REF_PACK is
file INFILE : text is in "in.dat";
file OUTFILE: text is out "out.dat";
end REF_PACK;
variable VEC_LINE : line;
variable VEC_VAR : bit_vector(0 to 7);
file VEC_FILE : text is in "stim.vec";
begin
while not endfile(VEC_FILE) loop
readline (VEC_FILE, VEC_LINE);
read (VEC_LINE, VEC_VAR);
A_BUS <= VEC_VAR;
wait for 10 ns;
end loop;
wait;
end process READ_FILE;
Les fichiers textes sont écrits en utilisant les sous programmes write et writeline, définis dans le packagestd.textio:
variable VEC_LINE : line;
file VEC_FILE : text is out "results";
begin
-- strobe OUT_DATA on falling edges of CLK and write value out to file
if CLK='0' then
write (VEC_LINE, OUT_DATA);
writeline (VEC_FILE, VEC_LINE);
end if;
end process WRITE_FILE;
La déclaration de fichier n’est pas supportée par les outils de synthèse.
Syntaxe : optional_label: for parameter in rangeloop
end loop optional_label;
L’instruction for loop definie les paramètres d’une boucle dans l’intervalle spécifié. Par exemple, l’intervalle 0 to 3 implique le type integer:
begin
Z <= "0000";
for I in 0 to 3 loop if (A = I) then Z(I) <= '1';
end if;
end loop;
end process;
variable TMP : std_ulogic;
begin
TMP := '0';
for I in A'low to A'high loop TMP := TMP xor A(I);
end loop;
ODD <= TMP;
end process;
type COLOUR is ARRAY (PRIMARY) of integer range 0 to 255;
signal VIDEO: COLOUR;
signal V_BUS: INTEGER range 0 to 255;
-- other statements
MUX: process
begin
for SEL in PRIMARY loop
V_BUS <= VIDEO(SEL);
wait for 10 ns;
end loop;
end process MUX;
if (REPEAT ='1') then I:= I-1; --
end if;
end loop;
L’instruction for loop est supportée par les outils de synthèse à condition que:
(1) l’indice de boucle soit statique (c.a.d le nombre d’itération est pré défini), et (2) la boucle ne contienne pas d’instruction wait.
Syntaxe : function function_name (parameter_list) return type is
begin
sequential statements
end function_name;
Une function ne peut avoir que des paramètres d’entrée, le mode (direction) n’est pas spécifié:
begin
if X then return '1';
else return '0';
end if;
end BOOL_TO_SL;
variable TMP : std_ulogic := '0';
begin
for J in X'range loop TMP := TMP xor X(J);
end loop; -- works for any size X
return TMP;
end PARITY;
Une function de type-conversion peut être appelée dans le port map, pour associer le port type au signal type. Si une function est définie dans un package, son corps (ses instuctions) doit être placé dans le package body :
function PARITY (X : bit_vector) return bit;
end REF_PACK;
package body REF_PACK is
function PARITY (X : bit_vector) return bit is
begin
-- function code
end PARITY;
end REF_PACK;
begin
PARITY_BYTE <= PARITY(DATA_BYTE);
PARITY_WORD <= PARITY(DATA_WORD);
end FUNCTIONS;
Les functions définies par l’utilisateurs sont supportées par les outils de synthèse.
Syntaxe : label: for parameter in range generate
end generate label;
L’instruction for...generate est généralement utilisée pour instancier des "arrays" de components. Le paramètre de generate peut être utiliser pour indexer les signaux associés aux component ports:
component REG
port(D,CLK,RESET : in std_ulogic;
Q : out std_ulogic);
end component;
begin
GEN_REG: for I in 0 to 3 generate
REGX : REG port map(DIN(I), CLK, RESET, DOUT(I));
end generate GEN_REG;
end GEN;
Les labels d’instance dans une instruction generate n’ont pas besoin d’être indéxés:
component FULLADD port (A,B,CIN : in bit; SUM, CARRY : out bit);
end component;
component HALFADD port(A,B : in bit; SUM, CARRY : out bit);
end component;
signal C : bit_vector(0 to 7);
begin
GEN_ADD: for I in 0 to 7 generate
LOWER_BIT: if I=0 generate U0: HALFADD port map (A(I),B(I),S(I),C(I));
end generate LOWER_BIT;
UPPER_BITS: if I>0 generate UX: FULLADD port map (A(I),B(I),C(I-1),S(I),C(I));
end generate UPPER_BITS;
end generate GEN_ADD;
COUT <= C(7);
end GEN;
Les instructions generate sont supportées par les outils de synthèse.
Syntaxe : entity entity_name is
port (port list);
end entity_name;
component component_name
generic (generic_list);
port (port_list);
end component;
instance_label: component_name
port map (port_association_list);
Les generics servent à passer les informations spécifques d’une instance vers une entity. Elles ne doivent pas avoir de mode (direction):
generic (N : integer);
port (A : in std_ulogic_vector (N-1 downto 0); ODD : out std_ulogic);
end PARITY;
generic (N : integer);
port (A : in std_ulogic_vector (N-1 downto 0); ODD : out std_ulogic);
end component;
generic map (N => 8)
port map (A => DATA_BYTE, ODD => PARITY_BYTE);
generic (DELAY: time := 1.0 ns);
port (A,B : in std_ulogic; Z : out std_ulogic);
end AN2_GENERIC;
architecture BEH of AN2_GENERIC is
begin
Z <= A and B after DELAY;
end A;
Habituellement, seuls les generics de type integer
sont supportés.
Syntaxe : if condition_1 then sequential statements
begin
if (EN = '1') then Q <= D;
end if;
end process;
--A condition is any boolean expression:
process (ALARM_TIME, CURRENT_TIME)
variable AL_EQ_CUR: boolean;
begin
AL_EQ_CUR := (ALARM_TIME=CURRENT_TIME);
if AL_EQ_CUR then SOUND_ALARM <= '1';
else SOUND_ALARM <= '0';
end if;
end process;
begin
if RESET = '1' then COUNT <= 0;
elsif CLK'event and CLK='1' then
if (COUNT >= 9) then COUNT <= 0;
else COUNT <= COUNT + 1;
end if;
end if;
end process;
when WAITING =>
if CPU_DATA_VALID = '1' then
CPU_DATA_READ <= '1';
READ_CPU_STATE <= DATA1;
end if;
when DATA1 =>
-- other branches of thecase statement
end case;
L’instruction if est généralement synthètisable.
Syntaxe : library library_name, another_library_name;
Règles et Exemples
La clause library doit apparaître avant le début du design unit:
use IEEE.STD_LOGIC_1164.all;
entity WIDGET is-- etc.
end WIDGET;
Lorsque plusieurs primary design units, dans le même fichier, utilisent une même library, la clause library doit être répétée avant chaque unit.
Les librairies work et std n’ont pas à être déclarées. Chaque unit est implicitement par :
library STD;
use STD.STANDARD.all;
La clause library est ignorée par les outils de synthèse.
Syntaxe : voir les exemples
Règles et Exemples
Les literals numérique avec un point décimalsont considérés comme des réels, et sans point décimal comme des entiers :
constant FREEZE : integer := 32;
constant TEMP : real := 32.0;
Les literals numérique peuvent être représentés dans n’importe quelle base de 2 à 16. Il peuvent aussi être scindés en utilisant le caractère souligné :
B_INT <= 2#1010_1010#;
MONEY := 1_000_000.0;
FACTOR := 2.2E-6;
Les literals de type time (ou d’un autre type physique) doit avoir une unité. Le symbole de l’unité doit être précédé d’un espace:
constant DEL2 :time := 2.27 us;
type T_STATE is (IDLE, READ, END_CYC);
signal CLK : MY_LOGIC := '0';
signal STATE : T_STATE := IDLE;
constant MSG : string := "Hello";
BIT_9_BUS <= O"353";
BIT_16_BUS <= X"AA55";
Les literals sont supportés par les outils de synthèse, s’ils appartiennent à un type acceptable.
Syntaxe : voir les exemples
Règles et Exemples
Les noms (ou identificateurs) sont constitués de lettres, chiffres et souligné (underscore):
signal SOUND_ALARM : std_ulogic;
AN_EXAMPLE_NAME
an_example_name
signal _BUS_16_BIT_ : integer; --
signal BUS_16_BIT : integer; --
Aucun mot clé du langage VHDL (signal, bus, component, etc.) ne peut être utilisé comme nom.
Effets sur la synthèse
Les noms légaux sont supportés par les outils de synthèse. Certains tronquent les noms trop longs.
Syntaxe : next;
next loop_label when condition;
L’instruction Next permet de terminer prématurément une boucle :
if SKIP = '1' then next;
end loop;
begin
Z <= "0000";
for I in 0 to 3 loop
next when A /= I;
Z(I) <= '1';
end loop;
end process;
begin
RESETLOOP: loop
VALID_CHECK: while (CPU_DATA_VALID /= '1') loop
wait until rising_edge(CLK) or RESET = '1';
next RESETLOOP when RESET='1';
end loop VALID_CHECK;
CPU_DATA_READ <= '1';
wait until rising_edge(CLK);
LOCAL_BUFFER <= DATA_BUS;
wait until rising_edge(CLK);
CPU_DATA_READ <= '0';
end loop RESETLOOP;
end process READ_BUS;
L’instruction next est supportée par certains outils de synthèse.
Syntaxe : null;
Règles et Exemples
Null est une instruction qui ne " fait rien ".
when "00" => CPU_DATA_TMP := (B & A) - OPERAND;
when "01" => CPU_DATA_TMP := (B & A) + OPERAND;
when "10" => CPU_DATA_TMP := (A & B) - OPERAND;
when "11" => CPU_DATA_TMP := (A & B) + OPERAND;
when others => null;
end case;
L’instruction null est supportée par les outils de synthèse.
Syntaxe : voir les exemples
Règles et Exemples
Les opérateurs logiques sont pré définis pour les types bit, boolean, bit_vector, linear arrays of boolean, std_logic et std_logic_vector. Ils renvoient une valeur de même type:
> -- greater than
<= -- less than or equal to
>= -- greater than or equal to
constant ARR2 :bit_vector := "01";
L’opérateurs & est utilisé pour concatener les tableaux ou ajouter des éléments à un tableau:
BYTE <= A_BUS & B_BUS;
signal REAL1, REAL2: real := 6.7;
INT1 <= INT1 + 3;
REAL1 <= REAL2 - 2.2;
INT2 <= INT1 * REAL1; --
INT2 <= INT1 * INTEGER(REAL1);
REAL2 <= REAL1 / 42.3;
Effets sur la synthèse
La plupart des opérateurs sont synthèsisables.
Syntaxe : package package_name is
end package_name;
Les déclarations sont typiquement les suivantes: type, subtype, constant, file, alias, component, attribute, function, procedure:
constant SOME_FLAG : bit_vector := "11111111";
type STATE is (RESET,IDLE,ACKA);
component HALFADD
port(A,B : in bit; SUM,CARRY : out bit);
end component;
end DEMO_PACK;
entity DEMO is
port (Z: out bit_vector(7 downto 0));
end DEMO;
architecture BEHAVE of DEMO is
begin
Z <= SOME_FLAG;
end BEHAVE;
Une constante déclarée dans un package doit être différée. Cela signifie que sa valeur sera définie dans le package body. La valeur peut être modifiée en re-analysant le seul package body:
constant C : integer;
end P;
package body P is
constant C : integer := 200;
end P;
Les Packages sont supportés par les outils de synthèse.
Les déclarations synthésisable et non-synthésisable
sont placées dans des packages différents
Syntaxe : package body package_name is
declarations
subprogram bodies
end package_name;
Lorsqu’une procedure ou une function est déclarée dans un package, son corps doit être placé dans le package body:
procedure PARITY
(signal X : in bit_vector;
signal Y : out bit);
end REF_PACK;
package body REF_PACK is
procedure PARITY
(signal X : in bit_vector;
signal Y : out bit) is
begin
-- procedure code
end PARITY;
end REF_PACK;
Une constante déclarée dans un package doit être différée. Cela signifie que sa valeur sera définie dans le package body. La valeur peut être modifiée en re-analysant le seul package body:
constant C : integer;
end P;
package body P is
constant C : integer := 200;
end P;
Chaque package ne peut avoir qu’un seul body.
Effets sur la synthèse
Les Package bodies sont supportés par les outils de synthèse.
Le package body doit se trouver dans le même fichier que le package.
Syntaxe : procedure procedure_name (parameter_list) is
begin
sequential statements
end procedure_name;
Les procedures ont des paramètres de mode in, out ou inout. Ils peuvent être signal, variable ou constant. Par défaut un paramètre in est de type constant . Out et inout est de type variable.
(ALARM_TIME, CURRENT_TIME : in digit;
SHOW_A : in std_ulogic;
signal DISPLAY_TIME : out digit) is
begin
if (SHOW_A = '1') then DISPLAY_TIME <= ALARM_TIME;
else DISPLAY_TIME <= CURRENT_TIME;
end if;
end DISPLAY_MUX;
...
begin
DISPLAY_MUX (ALARM_TIME, CURRENT_TIME, SHOW_A, DISPLAY_TIME);
end SUBPROG;
(signal X : in std_ulogic_vector;
signal Y : out std_ulogic) is
variable TMP : std_ulogic := '0';
begin
for J in X'range loop TMP := TMP xor X(J);
end loop; -- works for any size X
Y <= TMP;
end PARITY;
Si une procedure est définie dans un package, son corps doit être placé dans le package body:
procedure PARITY
(signal X : in std_logic_vector;
signal Y : out std_logic);
end REF_PACK;
package body REF_PACK is
procedure PARITY
(signal X : in std_logic_vector;
signal Y : out std_logic) is
begin
-- procedure code
end PARITY;
end REF_PACK;
Les procedures sont supportées par les outils de synthèse. Elles ne doivent pas contenir d’instruction wait.
Syntaxe : optional_label: process (optional sensitivity list)
declarations
La sensitivity list est une liste de signaux. Un changement d’une ou plusieurs des valeurs des signaux provoque l’activation du process:
begin
if (ALARM_TIME = CURRENT_TIME) then SOUND_ALARM <= '1';
else SOUND_ALARM <= '0';
end if;
end process;
begin
if (ALARM_TIME = CURRENT_TIME) then SOUND_ALARM <= '1';
else SOUND_ALARM <= '0';
end if;
wait on ALARM_TIME, CURRENT_TIME;
end process;
Un process peut contenir n’importe quelle instruction séquentielle.
Effets sur la synthèse
Les Processes sont synthésisable, pourvu qu’ils respectent certaines formes:
Un "clocked process" doit avoir soit une instruction wait ou une sensitivity list. Pour un tel process, des registres sont implémentés à chaque assignation de signal:
begin
wait until CLK'event and CLK='1';
Q1 <= D1;
end process;
SENSE_PROC: process (CLK)
begin
if CLK'event and CLK='1' then Q2 <= D2;
end if;
end process;
begin
Z <= B;
if SEL='1' then Z <= A;
end if;
end process;
Syntaxe : type'(expression)
Règles et Exemples
Une expression qualifiée est un expression avec un type clairement explicité.
bit_vector'("0010")
std_logic_vector'("0010")
signal P_STD : std_logic;
signal P_BIT : bit;
function PARITY (X : bit_vector) return bit is
begin
-- function code
end PARITY;
function PARITY (X : std_logic_vector) return std_logic is
begin
-- function code
end PARITY;
begin
P_BIT <=PARITY(bit_vector'("00100"));
P_STD <= PARITY(std_logic_vector'("10101"));
end OVER;
port(A,B : in std_ulogic;
VALUE: out integer range 0 to 9);
end CONCAT;
architecture BEHAVIOURAL of CONCAT is
subtype T_2 is std_ulogic_vector(1 downto 0);
begin
process(A,B)
begin
case T_2'(A & B) is
when "00" => VALUE <= 0;
when "01" => VALUE <= 1;
when "10" => VALUE <= 2;
when "11" => VALUE <= 3;
when others => VALUE <= 9;
end case;
end process;
end BEHAVIOURAL;
Les expressions qualifiése sont supportées par les outils de synthèse.
Syntaxe : signal signal_name : type;
signal COUNT : integer range 0 to 15;
signal CLK, RESET : std_ulogic := '0';
signal ALARM_TIME : T_CLOCK_TIME := (1,2,0,0);
signal CONDITION : boolean := false;
-- I will initialise to 0
signal X : std_logic;
-- X will initialise to 'U'
signal TRI_BIT: std_logic;
begin
TRI_BIT <= BIT_1 when EN_1 = '1' else 'Z';
TRI_BIT <= BIT_2 when EN_2 = '1' else 'Z';
end COND;
Les ports déclarés dans une entity sont accessibles comme signaux dans l’architecture(s) associée et n’ont pas besoin d’être re-déclaré.
Un signal de type résolu doit être déclaré comme signal résolu
signal signal_name : resolved_type signal_kind;
Le mot clé "signal kind" doit être un registre ou un bus. Les siganux résolus gardés associés à un registre kind mémorisent leurs valeurs lorsque la source est déconnectée, alors que les signaux associés a un bus kind comptent sur la fonction de résolution pour fournir la valeur de sortie.
Effets sur la synthèse
Les signaux sont accéptés en synthèse.
Le type signal kind pour un registre ou un bus est ignoré.
La plupart des outils reconnaissent les types std_logic_1164.
Syntaxe : signal_name <= expression;
Le concurrent signal assignment assigne une nouvelle valeur au signal cible chaque fois qu’un des signaux situés à droite du symbole <= change:
begin
SUM <= A xor B;
CARRY <= A and B;
end CONC;
begin
process (A,B)
begin
SUM <= A xor B;
CARRY <= A and B;
end process;
end SEQ;
constant PERIOD : time := 10 ns;
begin
SUM <= A xor B after 5 ns;
CARRY <= A and B after 3 ns;
CLK <= not CLK after PERIOD/2;
end DELAYS;
constant DELAY : time := 10 ns;
begin
O_PIN <= transport I_PIN after DELAY;
end TRANS;
Effets sur la synthèse
Les concurrent signal assignments sont en général synthésisable, providing they use types and operators acceptable to the synthesis tool.
Un signal assigné par des instructions simultanées sera synthétisé par de la logique combinationatoire. Les délais sont ignorés.
Syntaxe : signal_name <= expression_1 when condition_1
Chaque condition est une expression booléenne:
begin
Z <= A when X > 5 else
B when X < 5 else C;
end COND;
begin
Z <= A when X = 5 else
B when X < 10 else C;
end COND;
begin
Z <= A when X > 5; --
end COND;
Les conditional signal assignments peuvent être utilisés pour définir des buffers trois états, en utilisant les types std_logic et std_logic_vector. Remarquez l’utilisation de l’aggregate pour un bus:
signal TRI_BIT: std_logic;
signal TRI_BUS: std_logic_vector(0 to 7);
begin
TRI_BIT <= BIT_1 when EN_1 = '1' else 'Z';
TRI_BUS <= BUS_1 when EN_2 = '1' else (others => 'Z');
end COND;
les conditional signal assignments sont synthésisables.
Une assignation à 'Z' will génére une source 3-états.
Syntaxe : with expression select
Les règles sont les mêmes que pour l’instruction the case, c’est à dire que tout les choixdoivent être présents à moins que la clause others n’apparaîsse en dernier choix:
begin
with CMD select
Z <= B when "00",
C when "01",
A when others;
end SEL;
Z <= A when 0,
B when 1 to 3,
C when 4|6|8,
D when others;
Z <= A when 0,
B when 1 to 3,
C when 2|6|8, --
'X' when others;
type BYTE_POS is (LOWER, UPPER);
signal SEL: BYTE_POS;
begin
with SEL select
OBUS <= REG(0 to 7) when LOWER,
REG(8 to 15) when UPPER;
end COND;
Effets sur la synthèse
Les selected signal assignments sont synthésisables.
Une assignation à 'Z' will génére une source 3-états..
Syntaxe : signal_name <= expression;
Un sequential signal assignment prend effet lorsque le process est suspendu. Si il y a plus d’une assignation à un même signal avant la suspension, c’est la dernière assignation qui agira:
Si un signal est assigné dans un process et s’il est dans la sensitivity list, il re-active le process :
signal A,B,M,N,Y,Z : integer;
begin
process (A, B, M, N)
begin
M <= A;
N <= B;
Z <= M + N;
M <= 2*A;
Y <= M + N;
end process;
end EX1;
Un sequential signal assignment peut avoir un délai:
begin
SUM <= A xor B after 1.7 ns;
CARRY <= A and B after 1.2 ns;
end process;
Le sequential signal assignments est synthésisable.
Syntaxe : subtype subtype_name is base_type range range_constraint;
Règles et Exemples
Les assignations ne peuvent pas être faites entre objets de types différents.
type MY_LOGIC is ('0','1');
variable X_INT : integer := 22;
variable X_BUS : BUS_VAL := 22;
variable X_BIT : bit := '0';
variable X_MY : MY_LOGIC := '0';
X_BUS := X_INT; --
X_MY := X_BIT; --
subtype MY_LOGIC is std_ulogic range 'X' to 'Z';
variable X_INT : integer := 22;
variable X_BUS : BUS_VAL;
variable X_STD : std_ulogic := '0';
variable X_MY : MY_LOGIC;
X_BUS := X_INT; --
X_MY := X_STD; --
subtype POSITIVE is integer range 1 to integer'high;
subtype XO1Z is std_ulogic range 'X' to 'Z';
subtype UXO1 is std_ulogic range 'U' to '1';7
La plupart des outils acceptent les subtypes.
Syntaxe : target_type (closely_related_expression) conversion_function (expression)
Règles et Exemples
Les objets dont le type est défini par l’utilisateur ne peuvent pas être assigné par des objects de types proches. Une conversion de type permet l’assignation:
variable X_INT : integer := 22;
variable X_BUS : BUS_VAL;
X_BUS := X_INT; --
X_BUS := BUS_VAL(X_INT);
1) les types integer et real,
(2) les types tableau dont les longueurs, les indices et les éléments correspondent:
signal TYPE_BUS : T_BYTE;
signal VEC_BUS : std_ulogic_vector (7 downto 0);
...
TYPE_BUS <= VEC_BUS; --
TYPE_BUS <= T_BYTE(VEC_BUS);
signal X_STD: std_ulogic;
function BOOL_TO_SL(X : boolean) return std_ulogic is
begin
if X then return '1';
else return '0';
end if;
end BOOL_TO_SL;
...
X_STD <= X_BOOL; --
X_STD <= BOOL_TO_SL(X_BOOL);
Effets sur la synthèse
La plupart des outils accèptent les type conversion.
La plupart des outils acceptent les fonctions du package std_logic_1164.
Syntaxe : type type_name is type_definition;
Règles et Exemples
Les types scalaires ne mémorise qu’une seule valeur. Les types scalaires pré définis sont integer, real, bit, boolean et character. Des types numériques définis par l’utilisateur sont ainsi déclarés:
type T_REAL is range -9.9 to 9.9;
type BUS_VAL is range 0 to 255;
type MY_STATE is (RESET,IDLE,ACKA);
type MY_LOGIC is ('X','0','1','Z');
BYTE_ID: std_ulogic;
PARITY : std_ulogic;
ADDRESS: integer range 0 to 3;
DATA : std_ulogic_vector (3 downto 0);
end record;
...
TX_DATA.ADDRESS <= 3;
Les types physique permettent de décrires des unités physique comme, tension, température, etc. Le type pré défini time est type physique, il peut s’exprimer avec les unités suivantes:
ps (picosecond) sec (second)
ns (nanosecond) min (minute)
us (microsecond) hr (hour)
La plupart des outils acceptent les types: integer, boolean, bit, bit_vector, les types std_logic_1164.
Syntaxe : use library_name.primary_unit_name;
La clause use doit apparaître avant le début de la description. Si l’unité à utiliser n’est pas dans la librairie work, la clause library doit la précéder:
use IEEE.STD_LOGIC_1164.all;
entity WIDGET is
-- etc.
end WIDGET;
Lorsque plusieurs primary design units dans le même fichier utilisent les mêmes librairies il faut répéter la clause use avant chacune d’elles.
Le dernier champ de la clause use peut être remplacer par all, pour accéder tout les élément du design unit, ou toutes les design units d’une librairie:
use MY_LIB.MY_PACK.all;
configuration ASIC_TECH of ENT is
for GATE_ARCH
use ASIC_LIB.all;
end for;
end ASIC_TECH;
La plupart des outils acceptent la clause use.
Syntaxe : variable_name := expression;
Règles et Exemples
variable X : integer range 0 to 7;
begin
if SEL = '1' then X := B;
else X := C;
end if;
Z <= A + X;
end process;
signal A,B,Y,Z : integer;
begin
process (A, B)
variable M, N : integer;
begin
M := A;
N := B;
Z <= M + N;
M := 2*A;
Y <= M + N;
end process;
end EX1;
Une variable, dans un process peut se comporter comme un registre, elles conservent leurs valeurs entre deux activation du process:
variable Q : std_ulogic;
begin
if CLK'event and CLK='1' then
PULSE <= D and not(Q);
Q := D;
-- PULSE and Q act as registers
end if;
end process;
La plupart des outils acceptent les assignations de variable.
Les variables déclrées dans un sous programme sont synthésisées par de la logique combinatoire.
Syntaxe : variable variable_name : type;
variable COND : boolean := true;
variable IN_STRING : string(1 to 80);
variable M,N : bit := '1';
variable I : integer range 0 to 3;
variable MAKE_FRAME_STATE : T_MAKE_FRAME_STATE := RCV_HIGH;
-- initial value of I is 0
variable X : std_ulogic;
-- initial value of X is 'U'
variable TMP : std_ulogic := '0';
begin
for J in X'range loop TMP := TMP xor X(J);
end loop; --no need to initialise TMP
return TMP;
end PARITY;
variable TMP : std_ulogic := '0';
begin
TMP := '0';
-- in this example we need to reset
-- TMP to '0' each time the process
-- is activated
for I in A'low to A'high loop TMP := TMP xor A(I);
end loop;
ODD <= TMP;
end process;
La plupart des outils acceptent les variables.
Les variables déclrées dans un sous programme sont synthésisées par de la logique combinatoire.
Syntaxe : wait until condition;
wait for time;
wait;
L’instruction wait until suspend un process jusqu'à ce qu’un changement survienne sur l’un des signaux et que la condition devienne vraie. Un front montant sur NET_DATA_VALID et 3 fronts montants sur CLK sont nécessaire pour que le process soit effectué:
L’attribut 'event paraît redondant, mais beaucoup d’outils de synthèse en ont besoin:
WAIT_PROC: process
begin
wait until CLK'event and CLK='1';
Q1 <= D1;
end process;
L’instruction wait on équivalente à une sensitivity list. Ces processes sont identiques:
begin
-- sequential statements
end process;
begin
EN_1 <= '0';
EN_2 <= '1';
wait for 10 ns;
EN_1 <= '1';
EN_2 <= '0';
wait for 10 ns;
EN_1 <= '0';
wait for 10 ns;
wait; -- end of test
end process STIMULUS;
(2) dans une procedure appelée par un process avec une sensitivity list,
(3)dans un function, ou une procedure appélée par une function.
La plupart des outils ne supporte que l’instruction wait until.
Syntaxe : while condition loop
end loop;
loop
sequential statements
end loop;
La boucle while répète la séquence d’instructiond si la condition est vraie. La condition est testée avant chaque itération:
variable I : integer range 0 to 4;
begin
Z <= "0000";
I := 0;
while (I <= 3) loop
if (A = I) then Z(I) <= '1';
end if;
I := I + 1;
end loop;
end process;
begin
while NOW < MAX_SIM_TIME loop
CLK <= not CLK ;
wait for PERIOD/2;
end loop;
wait;
variable I : integer range 0 to 4;
begin
Z <= "0000";
I := 0;
L1: loop
exit L1 when I = 4;
if (A = I) then Z(I) <= '1';
end if;
I := I + 1;
end loop;
end process;
Les boucles while et infinite loops sont supportées par les outils de synthèse.